package com.example.googlemap;

import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.libraries.navigation.ArrivalEvent;
import com.google.android.libraries.navigation.ListenableResultFuture;
import com.google.android.libraries.navigation.NavigationApi;
import com.google.android.libraries.navigation.Navigator;
import com.google.android.libraries.navigation.RoutingOptions;
import com.google.android.libraries.navigation.SimulationOptions;
import com.google.android.libraries.navigation.SupportNavigationFragment;
import com.google.android.libraries.navigation.Waypoint;

import java.util.Objects;

/**
 * Created by Danny on 2023/10/19
 */
public class ActivityNavigation extends AppCompatActivity {

    private static final String TAG = "google-map";
    private Navigator mNavigator;
    private SupportNavigationFragment mNavFragment;
    private double[] latlng; // 深圳北站
    private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
    private boolean startNav = true;
    private final Navigator.ArrivalListener mArrivalListener = new Navigator.ArrivalListener() {
        @Override
        public void onArrival(ArrivalEvent arrivalEvent) {
            if (arrivalEvent.isFinalDestination()){
                Log.d(TAG,"到达终点了");
                mNavigator.stopGuidance();
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_navigation);
        Button btBack = findViewById(R.id.btBack);
        Button btSwitch = findViewById(R.id.btSwitch);

        btBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });

        btSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (startNav){
                    mNavigator.clearDestinations();
                    btSwitch.setText( "start nav");
                    startNav = false;
                }else {
                    navigateToPlace(latlng[0], latlng[1]);
                    btSwitch.setText( "end nav");
                    startNav = true;
                }

            }
        });

        latlng = getIntent().getDoubleArrayExtra("location");
        checkPermission();
    }

    private void checkPermission() {
        if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
                android.Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this.getApplicationContext(),
                android.Manifest.permission.ACCESS_COARSE_LOCATION)
                == PackageManager.PERMISSION_GRANTED){
            initNavigationSdk();
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        }
    }

    /**
     * Starts the Navigation SDK and sets the camera to follow the device's location.
     * Calls the navigateToPlace() method when the navigator is ready.
     */
    private void initNavigationSdk() {
        NavigationApi.getNavigator(this, new NavigationApi.NavigatorListener() {
            /**
             * Handles errors from the Navigation SDK.
             * @param i The error code returned by the navigator.
             */
            @Override
            public void onError(int i) {
                switch (i) {
                    case NavigationApi.ErrorCode.NOT_AUTHORIZED:
                        Log.e(TAG, "Error loading Navigation SDK: Your API key is "
                                + "invalid or not authorized to use the Navigation SDK.");
                        break;
                    case NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED:
                        Log.e(TAG, "Error loading Navigation SDK: User did not accept "
                                + "the Navigation Terms of Use.");
                        break;
                    case NavigationApi.ErrorCode.NETWORK_ERROR:
                        Log.e(TAG, "Error loading Navigation SDK: Network error.");
                        break;
                    case NavigationApi.ErrorCode.LOCATION_PERMISSION_MISSING:
                        Log.e(TAG, "Error loading Navigation SDK: Location permission "
                                + "is missing.");
                        break;
                    default:
                        Log.e(TAG, "Error loading Navigation SDK: " + i);
                }
            }

            /**
             * Sets up the navigation UI when the navigator is ready for use.
             */
            @SuppressLint("MissingPermission")
            @Override
            public void onNavigatorReady(Navigator navigator) {
                Log.i(TAG, "Navigator ready.");
                mNavigator = navigator;
                mNavigator.addArrivalListener(mArrivalListener);
                mNavFragment = (SupportNavigationFragment) getSupportFragmentManager().findFragmentById(R.id.navFragment);
                if(mNavFragment != null){
                    mNavFragment.setForceNightMode(1);
                    mNavFragment.setHeaderEnabled(false);  // 关闭头部导航卡片
                    mNavFragment.setEtaCardEnabled(false); // 关闭底部Eta片
                    navigateToPlace(latlng[0], latlng[1]);
                }
            }
        });
    }

    /**
     * Requests directions from the user's current location to a specific place (provided
     * by the Google Places API).
     */
    private void navigateToPlace(double lat,double lng) {
        RoutingOptions routingOptions = new RoutingOptions();
        routingOptions.travelMode(RoutingOptions.TravelMode.WALKING);

        Waypoint destination;
        try {
            destination = Waypoint.builder().setLatLng(lat,lng).build();
        }catch (Exception e){
            Log.e(TAG, Objects.requireNonNull(e.getMessage()));
            return;
        }
        // Create a future to await the result of the asynchronous navigator task.
        ListenableResultFuture<Navigator.RouteStatus> pendingRoute = mNavigator.setDestination(destination,routingOptions);
        // Define the action to perform when the SDK has determined the route.
        pendingRoute.setOnResultListener(new ListenableResultFuture.OnResultListener<Navigator.RouteStatus>() {
            @Override
            public void onResult(Navigator.RouteStatus routeStatus) {
                switch (routeStatus) {
                    case OK:
                        // Hide the toolbar to maximize the navigation UI.
                        if (getActionBar() != null) {
                            getActionBar().hide();
                        }

                        customizeNavigationUI();

                        // Enable voice audio guidance (through the device speaker).
                        mNavigator.setAudioGuidance(
                                Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE);

                        // Simulate vehicle progress along the route for demo/debug builds.
//                        if (BuildConfig.DEBUG) {
//                            mNavigator.getSimulator().simulateLocationsAlongExistingRoute(
//                                    new SimulationOptions().speedMultiplier(50));
//                        }

                        // Start turn-by-turn guidance along the current route.
                        mNavigator.startGuidance();
                        break;
                    // Handle error conditions returned by the navigator.
                    case NO_ROUTE_FOUND:
                        Log.e(TAG,"Error starting navigation: No route found.");
                        break;
                    case NETWORK_ERROR:
                        Log.e(TAG,"Error starting navigation: Network error.");
                        break;
                    case ROUTE_CANCELED:
                        Log.e(TAG,"Error starting navigation: Route canceled.");
                        break;
                    default:
                        Log.e(TAG,"Error starting navigation: "
                                + routeStatus);
                }
            }
        });

    }

    /**
     * Customizes the navigation UI and the map.
     */
    @SuppressLint("MissingPermission")
    private void customizeNavigationUI() {
        // Set custom colors for the navigator.
        if (mNavFragment == null) {
           return;
        }
        // Set the camera to follow the device location with 'TILTED' driving view.
        mNavFragment.getMapAsync(new OnMapReadyCallback() {
                                     @Override
                                     public void onMapReady(GoogleMap googleMap) {
                                         Log.d(TAG,"设置地图图层相关");
//                                         setMyLocationMarker(googleMap);
                                         googleMap.followMyLocation(GoogleMap.CameraPerspective.TOP_DOWN_HEADING_UP);
                                     }
                                 }
        );
    }

    @SuppressLint("MissingPermission")
    private void setMyLocationMarker(GoogleMap googleMap){
        googleMap.setMyLocationEnabled(false);
        CameraPosition cameraPosition = googleMap.getCameraPosition();
        MarkerOptions markerOptions = new MarkerOptions()
                .position(new LatLng(cameraPosition.target.latitude,cameraPosition.target.longitude))
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_location));
        googleMap.addMarker(markerOptions);
    }


    /**
     * Handles the result of the request for location permissions.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) {
            if (grantResults.length == 0){
                Toast.makeText(ActivityNavigation.this,"没有权限授权请求",Toast.LENGTH_SHORT).show();
                return;
            }
            for (int grantResult: grantResults) {
                if (grantResult == PackageManager.PERMISSION_DENIED){
                    Toast.makeText(ActivityNavigation.this,"权限授权失败",Toast.LENGTH_SHORT).show();
                    return;
                }
            }
            initNavigationSdk();
        }
    }

    @Override
    protected void onDestroy() {
        mNavigator.clearDestinations();
        mNavigator.removeArrivalListener(mArrivalListener);
        mNavigator.cleanup();
        mNavigator = null;
        super.onDestroy();
    }
}